home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
loading
/
ADotOutExtrasAccessImpl.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-03
|
33KB
|
1,136 lines
/* begincopyright
Copyright (c) 1988-1990 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA 94304
endcopyright */
/*
* ADotOutExtrasAccessImpl.c
*
* Demers, October 2, 1990 9:12:12 am PDT
*
*/
#include <xr/BasicTypes.h>
#include <xr/Errno.h>
#include <xr/ADotOutExtrasPvt.h>
#include <sys/file.h>
/*
* configuration limits
*/
#define DEFAULT_EXTRA_SECTIONS 1
#define MAX_EXTRA_SECTIONS 16
/*
* error handling primitives
*/
#define ResIsError(res) \
((res) < 0)
#ifdef UNDEFINED
#define ResFromErrno(errno) \
( -(errno) )
#else
int ResFromErrno(e) int e; { return (-e); }
#endif
#define ReturnIfErrorRes(res) \
if( ((int)(res)) < 0 ) return (res)
#define ReturnIfWrongRes(res,wanted,err) \
if( (res) != (wanted) ) \
return( ResIsError(res) ? res : ResFromErrno(err) )
/*
* PCR extra subsec magic number
*/
#define MAGIC_STRING "PCRExtraSection"
static int
XR_aDotOutExtraMagic = 0;
int
XR_SetADotOutExtraMagic(magic)
int magic;
{
int ans = XR_aDotOutExtraMagic;
XR_aDotOutExtraMagic = magic;
return ans;
}
int
XR_GetADotOutExtraMagic()
{
int ans;
if( (ans = XR_aDotOutExtraMagic) == 0 ) {
(void)bcopy(MAGIC_STRING, ((char *)(&ans)), (sizeof ans));
XR_aDotOutExtraMagic = ans;
}
return ans;
}
/*
* internal I/O primitives
*/
static int
XR_AOXRead(lSeekProc, readProc, clientData, pos, buf, bytes)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_Pointer clientData;
int pos;
char *buf;
int bytes;
{
int ans, nread;
ans = (*lSeekProc)(pos, L_SET, clientData);
ReturnIfErrorRes(ans);
nread = 0;
for(;;) {
if( nread >= bytes ) return nread;
ans = (*readProc)(buf+nread, bytes-nread, clientData);
ReturnIfErrorRes(ans);
if( ans == 0 ) return nread;
nread += ans;
}
}
static int
XR_AOXWrite(lSeekProc, writeProc, clientData, pos, buf, bytes)
XR_IOPositionProc lSeekProc;
XR_IOXferProc writeProc;
XR_Pointer clientData;
int pos;
char *buf;
int bytes;
{
int ans, nwritten;
ans = (*lSeekProc)(pos, L_SET, clientData);
ReturnIfErrorRes(ans);
nwritten = 0;
for(;;) {
if( nwritten >= bytes ) return nwritten;
ans = (*writeProc)(buf+nwritten, bytes-nwritten, clientData);
ReturnIfErrorRes(ans);
if( ans == 0 ) return ResFromErrno(EIO);
nwritten += ans;
}
}
static int
ShiftLeftInFile(lSeekProc, readProc, writeProc, clientData,
to, from, bytes)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_IOXferProc writeProc;
XR_Pointer clientData;
int to;
int from;
int bytes;
{
int ans, nToMove;
char buf[2048];
while( bytes > 0 ) {
if( (nToMove = (sizeof buf)) > bytes ) nToMove = bytes;
ans = XR_AOXRead(lSeekProc, readProc, clientData, from, buf, nToMove);
ReturnIfWrongRes(ans,nToMove,EFMT);
from += nToMove;
ans = XR_AOXWrite(lSeekProc, writeProc, clientData, to, buf, nToMove);
ReturnIfWrongRes(ans,nToMove,EIO);
to += nToMove;
bytes -= nToMove;
}
return 0;
}
static int
ShiftRightInFile(lSeekProc, readProc, writeProc, clientData,
from, to, bytes)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_IOXferProc writeProc;
XR_Pointer clientData;
int from;
int to;
int bytes;
{
int ans, nToMove;
char buf[2048];
from += bytes;
to += bytes;
while( bytes > 0 ) {
if( (nToMove = (sizeof buf)) > bytes ) nToMove = bytes;
from -= bytes;
ans = XR_AOXRead(lSeekProc, readProc, clientData, from, buf, nToMove);
ReturnIfWrongRes(ans,nToMove,EFMT);
to -= bytes;
ans = XR_AOXWrite(lSeekProc, writeProc, clientData, to, buf, nToMove);
ReturnIfWrongRes(ans,nToMove,EIO);
bytes -= nToMove;
}
return 0;
}
/*
* a.out header manipulation
*/
static int
XR_GetExec(lSeekProc, readProc, clientData, a)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_Pointer clientData;
struct exec *a;
/*
Read the a.out header into *a.
Return 0 on success, (-errno) on failure.
*/
{
int ans;
ans = XR_AOXRead(lSeekProc, readProc, clientData,
/* pos=*/ 0, a, sizeof(*a));
ReturnIfWrongRes(ans,(sizeof(*a)),ENOEXEC);
if( N_BADMAG(*a) ) return( ResFromErrno(ENOEXEC) );
return 0;
}
/*
* struct extra_sections access
*/
typedef struct ExtraSectionsRep {
struct /* a.out.h . */ extra_sections es_extra;
int es_sizes[MAX_EXTRA_SECTIONS];
} * ExtraSections;
#define es_magic es_extra.extra_magic
#define es_nsects es_extra.extra_nsects
static int
XR_FindExtraSections(lSeekProc, readProc, clientData, esPos)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_Pointer clientData;
int *esPos;
/*
Store position of extra sections in *esPos.
Return 0 on success, (-errno) on failure.
*/
{
int ans, fileOff, stringsBytes;
struct exec a;
ans = XR_GetExec(lSeekProc, readProc, clientData, &a);
ReturnIfErrorRes(ans);
fileOff = N_STROFF(a);
ans = XR_AOXRead(lSeekProc, readProc, clientData,
fileOff, &stringsBytes, (sizeof stringsBytes));
ReturnIfWrongRes(ans, (sizeof stringsBytes), EFMT);
if( esPos != NIL ) *esPos = (fileOff + stringsBytes);
return 0;
}
static int
XR_WriteExtraSections(lSeekProc, writeProc, clientData, esPos, es)
XR_IOPositionProc lSeekProc;
XR_IOXferProc writeProc;
XR_Pointer clientData;
int esPos;
ExtraSections es;
/*
Write *es into file at specified position (length is self-described).
Return bytes written on success, (-errno) on failure.
*/
{
int ans;
int esBytes;
if( es == NIL ) return ResFromErrno(EFAULT);
if( es->es_nsects > MAX_EXTRA_SECTIONS ) return ResFromErrno(EBUG);
esBytes = (sizeof es->es_extra) + (es->es_nsects * sizeof(int));
ans = XR_AOXWrite(lSeekProc, writeProc, clientData,
esPos, es, esBytes);
ReturnIfWrongRes(ans, esBytes, EIO);
return esBytes;
}
static int
XR_ReadExtraSections(lSeekProc, readProc, clientData,
esPos, es, esMaxBytes)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_Pointer clientData;
int esPos;
struct ExtraSectionsRep * es;
int esMaxBytes;
/*
Get ExtraSections section from file at offset esPos,
store it in *es.
Return bytes read on success, (0 on end of file), (-errno) on failure.
*/
{
int ans;
int bytes;
int maxSections;
if( esMaxBytes < (sizeof es->es_extra) ) return ResFromErrno(EFAULT);
maxSections = (esMaxBytes - (sizeof es->es_extra)) / sizeof(int);
bytes = (sizeof es->es_extra);
ans = XR_AOXRead( lSeekProc, readProc, clientData,
esPos, es, bytes );
if( ans == 0 ) return 0;
ReturnIfWrongRes(ans, bytes, EFMT);
if( es->es_nsects > maxSections ) return ResFromErrno(EFMT);
bytes += (es->es_nsects * sizeof(int));
ans = XR_AOXRead( lSeekProc, readProc, clientData,
esPos, es, bytes );
ReturnIfWrongRes(ans, bytes, EFMT);
return bytes;
}
/*
* PCR subsection primitives
*/
char *
XR_GetEndOfGroupSubsecName()
{
return "eog";
}
int
XR_XSubsecHdr_GetHdrBytes(xssh)
XR_XSubsecHdr xssh;
{
int nameBytes, ans;
nameBytes = (1+strlen(xssh->xssh_name));
ans = XR_XSubsecHdr_sizeof(nameBytes);
if( (ans > (sizeof (*xssh)))
|| (XR_XSubsecHdr_hdrBytes(xssh, nameBytes) != ans) )
return ResFromErrno(EFMT);
return ans;
}
int
XR_XSubsecHdr_SetName(xssh, name)
XR_XSubsecHdr xssh;
char *name;
{
int nameBytes, hdrLen;
if( name == NIL ) name = "";
nameBytes = 1+strlen(name);
hdrLen = XR_XSubsecHdr_sizeof(nameBytes);
if( hdrLen > (sizeof (*xssh)) )
return ResFromErrno(ENAMETOOLONG);
(void)strcpy(xssh->xssh_name, name);
while( (nameBytes % sizeof(int)) != 0 ) {
xssh->xssh_name[nameBytes] = '\0';
nameBytes += 1;
}
XR_XSubsecHdr_hdrBytes(xssh, nameBytes) = hdrLen;
return hdrLen;
}
static int
XR_ReadXSubsecHdr(lSeekProc, readProc, clientData,
xsshPos, xssh)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_Pointer clientData;
int xsshPos;
XR_XSubsecHdr xssh;
{
int ans, xsshBytes;
ans = XR_AOXRead(lSeekProc, readProc, clientData,
xsshPos, xssh, (sizeof(*xssh)) );
ReturnIfErrorRes(ans);
if( ans < XR_XSubsecHdr_sizeof(1) )
return ResFromErrno(EFMT);
xsshBytes = XR_XSubsecHdr_GetHdrBytes(xssh);
ReturnIfErrorRes(xsshBytes);
if( (ans < xsshBytes) )
return ResFromErrno(EFMT);
return xsshBytes;
}
static int
XR_GetXSubsecHdrFromClientPos(lSeekProc, readProc, clientData, pos, xssh)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_Pointer clientData;
int pos;
XR_XSubsecHdr xssh;
{
int ans;
int xsshBytes;
if( pos < (sizeof xsshBytes) ) return ResFromErrno(EBUG);
ans = XR_AOXRead( lSeekProc, readProc, clientData,
pos-(sizeof xsshBytes), &xsshBytes, (sizeof xsshBytes) );
ReturnIfWrongRes(ans, (sizeof xsshBytes), EFMT);
if( pos < xsshBytes ) return ResFromErrno(EFMT);
return XR_ReadXSubsecHdr(lSeekProc, readProc, clientData,
pos-xsshBytes, xssh );
}
static int
XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData, xsshPos, xssh)
XR_IOPositionProc lSeekProc;
XR_IOXferProc writeProc;
XR_Pointer clientData;
int xsshPos;
XR_XSubsecHdr xssh;
{
int ans;
int bytes;
bytes = XR_XSubsecHdr_GetHdrBytes(xssh);
ans = XR_AOXWrite(lSeekProc, writeProc, clientData, xsshPos, xssh, bytes);
ReturnIfWrongRes(ans, bytes, EIO);
return ans;
}
static int
XR_WriteEndOfGroupSubsec(lSeekProc, writeProc, clientData,
xsshPos, xssh, groupBytes )
XR_IOPositionProc lSeekProc;
XR_IOXferProc writeProc;
XR_Pointer clientData;
int xsshPos;
XR_XSubsecHdr xssh;
int groupBytes;
/*
Input value of groupbytes
<= 0 ==> abs value, doesn't count end-of-group subsec itself.
*/
{
int ans;
int xsshBytes;
struct XR_XSubsecHdrRep xsshRep;
if( xssh == NIL ) xssh = &xsshRep;
xssh->xssh_magic = XR_GetADotOutExtraMagic();
xsshBytes = XR_XSubsecHdr_SetName(xssh, XR_GetEndOfGroupSubsecName());
ReturnIfErrorRes(xsshBytes);
if( groupBytes <= 0 )
groupBytes = (-groupBytes) + xsshBytes + sizeof(int);
xssh->xssh_subsecBytes = groupBytes;
ans = XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData,
xsshPos, xssh);
ReturnIfWrongRes(ans, xsshBytes, EIO);
ans = XR_AOXWrite( lSeekProc, writeProc, clientData,
xsshPos+xsshBytes, &(xssh->xssh_subsecBytes), sizeof(int) );
ReturnIfWrongRes(ans,sizeof(int),EIO);
return groupBytes;
}
static int
XR_FindXSecInExtraSections(lSeekProc, readProc, clientData,
esPos, es, xsecIndex, xsecPos)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_Pointer clientData;
int esPos;
ExtraSections es;
int * xsecIndex;
int * xsecPos;
/*
Find position of PCR extra section in supplied Extra Sections header.
Return 0 on success, (-errno) on error.
*/
{
int ans;
unsigned fileOff;
int magic;
int i;
fileOff = esPos + (sizeof es->es_extra) + (es->es_nsects * sizeof(int));;
/* skip extra sections header itself */
for( i = 0; i < es->es_nsects; i++ ) {
if( es->es_sizes[i] == 0 ) break;
ans = XR_AOXRead(lSeekProc, readProc, clientData,
fileOff, &magic, (sizeof magic));
ReturnIfWrongRes(ans, (sizeof magic), EFMT);
if( magic == XR_GetADotOutExtraMagic() ) break;
fileOff += es->es_sizes[i];
}
if( xsecPos != NIL ) *xsecPos = fileOff;
if( xsecIndex != NIL ) *xsecIndex = i;
if( i >= es->es_nsects ) return ResFromErrno(ENOSPC);
/* TEMPORARY: index must be 0! */
if( i != 0 ) return ResFromErrno(ENOSPC);
return 0;
}
static int
XR_GetXSec(lSeekProc, readProc, writeProc, clientData,
xsecPos, xsecBytes)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_IOXferProc writeProc;
XR_Pointer clientData;
int *xsecPos;
int *xsecBytes;
{
int ans;
int esPos;
int xsecIndex;
struct XR_XSubsecHdrRep xsshRep;
struct ExtraSectionsRep esRep;
/* get extra sections */
ans = XR_FindExtraSections(lSeekProc, readProc, clientData, &esPos);
ReturnIfErrorRes(ans);
ans = XR_ReadExtraSections(lSeekProc, readProc, clientData,
esPos, &esRep, (sizeof esRep) );
ReturnIfErrorRes(ans);
if( ans == 0 ) {
if( writeProc == NIL ) return ResFromErrno(ENOSPC);
/* put empty extra sections header in esRep */
/* (it will be written below) */
esRep.es_magic = EXTRA_MAGIC;
esRep.es_nsects = DEFAULT_EXTRA_SECTIONS;
(void)bzero( esRep.es_sizes,
esRep.es_nsects*sizeof(int) );
}
/* get PCR extra section */
ans = XR_FindXSecInExtraSections(lSeekProc, readProc, clientData,
esPos, &esRep, &xsecIndex, xsecPos);
ReturnIfErrorRes(ans);
if( xsecIndex >= esRep.es_nsects )
return ResFromErrno(ENOSPC);
if( ((xsecIndex+1) < esRep.es_nsects)
&& (esRep.es_sizes[(xsecIndex+1)] != 0) )
return ResFromErrno(ENOSPC);
(*xsecBytes) = esRep.es_sizes[xsecIndex];
if( (*xsecBytes) == 0 ) {
if( writeProc == NIL ) return ResFromErrno(ENOSPC);
ans = XR_WriteEndOfGroupSubsec(
lSeekProc, writeProc, clientData,
*xsecPos, &xsshRep, 0 );
ReturnIfErrorRes(ans);
(*xsecBytes) += RNDUPWORDSZ(xsshRep.xssh_subsecBytes);
esRep.es_sizes[xsecIndex] = (*xsecBytes);
ans = XR_WriteExtraSections(lSeekProc, writeProc, clientData,
esPos, &esRep);
ReturnIfErrorRes(ans);
}
return 0;
}
static int
XR_UpdateExtraSections(lSeekProc, readProc, writeProc, clientData, xsecLim)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_IOXferProc writeProc;
XR_Pointer clientData;
int xsecLim;
{
int ans;
int esPos;
int xsecIndex;
int xsecPos;
int xsecBytes;
struct ExtraSectionsRep esRep;
/* get extra sections */
ans = XR_FindExtraSections(lSeekProc, readProc, clientData, &esPos);
ReturnIfErrorRes(ans);
ans = XR_ReadExtraSections(lSeekProc, readProc, clientData,
esPos, &esRep, (sizeof esRep) );
ReturnIfErrorRes(ans);
if( ans == 0 ) return ResFromErrno(EBUG);
/* get PCR extra section */
ans = XR_FindXSecInExtraSections(lSeekProc, readProc, clientData,
esPos, &esRep, &xsecIndex, &xsecPos);
ReturnIfErrorRes(ans);
if( xsecIndex >= esRep.es_nsects )
return ResFromErrno(EBUG);
if( ((xsecIndex+1) < esRep.es_nsects)
&& (esRep.es_sizes[(xsecIndex+1)] != 0) )
return ResFromErrno(EBUG);
xsecBytes = esRep.es_sizes[xsecIndex];
if( xsecBytes == 0 )
return ResFromErrno(EBUG);
/* update and write extra sections hdr */
esRep.es_sizes[xsecIndex] = RNDUPWORDSZ(xsecLim) - xsecPos;
ans = XR_WriteExtraSections(lSeekProc, writeProc, clientData,
esPos, &esRep);
ReturnIfErrorRes(ans);
return 0;
}
/*
* EXPORTS
*/
int
XR_EnumerateExtraSubsecs(lSeekProc, readProc, clientData,
subsecPos, callbackProc, callbackData)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_Pointer clientData;
int subsecPos;
XR_ExtraSubsecCallbackProc callbackProc;
XR_Pointer callbackData;
{
int ans;
int xsecPos;
int xsecBytes;
int xsecLim;
int xsshPos;
int xsshBytes;
int groupBytes;
char *subsecName;
int subsecBytes;
struct XR_XSubsecHdrRep xsshRep;
ans = XR_GetXSec(lSeekProc, readProc, NIL, clientData,
&xsecPos, &xsecBytes);
if( ans == ResFromErrno(ENOSPC) ) return 0;
ReturnIfErrorRes(ans);
xsecLim = xsecPos + xsecBytes;
if( subsecPos == 0 ) {
xsshPos = xsecPos;
} else if( subsecPos == (-1) ) {
/* read end-of-group subsec, use it to find beginning of last group */
ans = XR_GetXSubsecHdrFromClientPos(lSeekProc, readProc, clientData,
xsecLim-(sizeof groupBytes), &xsshRep);
ReturnIfErrorRes(ans);
if( strcmp(xsshRep.xssh_name, XR_GetEndOfGroupSubsecName()) != 0 )
return ResFromErrno(EFMT);
ans = XR_AOXRead(lSeekProc, readProc, clientData,
xsecLim-(sizeof groupBytes), &groupBytes, (sizeof groupBytes) );
ReturnIfWrongRes(ans, (sizeof groupBytes), EFMT);
xsshPos = xsecLim - groupBytes;
} else {
ans = XR_GetXSubsecHdrFromClientPos(lSeekProc, readProc, clientData,
subsecPos, &xsshRep);
ReturnIfErrorRes(ans);
xsshPos = subsecPos - ans + RNDUPWORDSZ(xsshRep.xssh_subsecBytes);
}
while( xsshPos < xsecLim ) {
ans = XR_ReadXSubsecHdr(lSeekProc, readProc, clientData,
xsshPos, &xsshRep );
ReturnIfErrorRes(ans);
xsshBytes = ans;
subsecName = xsshRep.xssh_name;
subsecPos = xsshPos + xsshBytes;
subsecBytes = xsshRep.xssh_subsecBytes - xsshBytes;
ans = (*callbackProc)( subsecName, subsecPos,
subsecBytes, callbackData );
ReturnIfWrongRes(ans, 0, 0);
xsshPos += RNDUPWORDSZ(xsshRep.xssh_subsecBytes);
}
return 0;
}
/* Find implemented in terms of Enumerate */
typedef struct FindExtraSubsecCallbackDataRep {
char *fescd_subsecName;
int fescd_subsecPos;
int fescd_subsecBytes;
} * FindExtraSubsecCallbackData;
int
MyExtraSubsecCallbackProc(subsecName, subsecPos, subsecBytes, fescd)
char * subsecName;
int subsecPos;
int subsecBytes;
FindExtraSubsecCallbackData fescd;
{
if( strcmp(subsecName, fescd->fescd_subsecName) == 0 ) {
fescd->fescd_subsecPos = subsecPos;
fescd->fescd_subsecBytes = subsecBytes;
return 1;
}
return 0;
}
int
XR_FindExtraSubsec(lSeekProc, readProc, clientData,
subsecName, subsecPos, subsecBytes)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_Pointer clientData;
char * subsecName;
int * subsecPos;
int * subsecBytes;
{
int ans;
int startPos = 0;
struct FindExtraSubsecCallbackDataRep fescdr;
if( (subsecName == NIL) || (subsecName[0] == '\0') )
return ResFromErrno(EINVAL);;
if( subsecPos != NIL ) startPos = *subsecPos;
fescdr.fescd_subsecName = subsecName;
fescdr.fescd_subsecPos = 0;
fescdr.fescd_subsecBytes = 0;
ans = XR_EnumerateExtraSubsecs(lSeekProc, readProc, clientData,
startPos, MyExtraSubsecCallbackProc, &fescdr);
if( subsecPos != NIL ) *subsecPos = fescdr.fescd_subsecPos;
if( subsecBytes != NIL ) *subsecBytes = fescdr.fescd_subsecBytes;
return ans;
}
/* Delete implemented in terms of Enumerate */
typedef struct DeleteCopierDataRep {
int dcd_entryCnt;
XR_IOPositionProc dcd_lSeekProc;
XR_IOXferProc dcd_readProc;
XR_IOXferProc dcd_writeProc;
XR_Pointer dcd_clientData;
XR_ExtraSubsecCallbackProc dcd_underDallbackProc;
XR_Pointer dcd_underCallbackData;
int dcd_toPos;
} * DeleteCopierData;
static int
DeleteCopier(subsecName, subsecPos, subsecBytes, dcd)
char * subsecName;
int subsecPos;
int subsecBytes;
DeleteCopierData dcd;
{
int ans;
bool deleteMe;
int fromPos;
int fromBytes;
struct XR_XSubsecHdrRep xsshRep;
dcd->dcd_entryCnt += 1;
ans = XR_GetXSubsecHdrFromClientPos( dcd->dcd_lSeekProc,
dcd->dcd_readProc, dcd->dcd_clientData,
subsecPos, &xsshRep );
ReturnIfErrorRes(ans);
if( dcd->dcd_entryCnt == 1 ) dcd->dcd_toPos = (subsecPos - ans);
fromPos = subsecPos - ans;
fromBytes = xsshRep.xssh_subsecBytes;
ans = (*(dcd->dcd_underDallbackProc))(subsecName, subsecPos, subsecBytes,
dcd->dcd_underCallbackData);
ReturnIfErrorRes(ans);
if( ans == 0 ) /* subsec must be preserved */ {
if( dcd->dcd_toPos != fromPos ) {
ans = ShiftLeftInFile(
dcd->dcd_lSeekProc, dcd->dcd_readProc,
dcd->dcd_writeProc, dcd->dcd_clientData,
dcd->dcd_toPos, fromPos, fromBytes);
ReturnIfErrorRes(ans);
}
dcd->dcd_toPos += RNDUPWORDSZ(fromBytes);
}
return 0;
}
int
XR_DeleteExtraSubsecs(lSeekProc, readProc, writeProc, fTruncateProc, clientData,
subsecPos, callbackProc, callbackData)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_IOXferProc writeProc;
XR_IOPositionProc fTruncateProc;
XR_Pointer clientData;
int subsecPos;
XR_ExtraSubsecCallbackProc callbackProc;
XR_Pointer callbackData;
{
int ans;
int esPos;
int xsecIndex;
struct ExtraSectionsRep esRep;
struct DeleteCopierDataRep dcdRep;
/* enumerate subsecs, copying those to be preserved */
dcdRep.dcd_entryCnt = 0;
dcdRep.dcd_lSeekProc = lSeekProc;
dcdRep.dcd_readProc = readProc;
dcdRep.dcd_writeProc = writeProc;
dcdRep.dcd_clientData = clientData;
dcdRep.dcd_underDallbackProc = callbackProc;
dcdRep.dcd_underCallbackData = callbackData;
dcdRep.dcd_toPos = (-1);
ans = XR_EnumerateExtraSubsecs(lSeekProc, readProc, clientData,
subsecPos, DeleteCopier, &dcdRep);
ReturnIfErrorRes(ans);
if( dcdRep.dcd_entryCnt == 0 ) /* there was nothing to delete */ {
return 0;
}
/* truncate file to its new length */
if( fTruncateProc != NIL ) {
ans = (*fTruncateProc)(dcdRep.dcd_toPos, L_SET, clientData);
ReturnIfErrorRes(ans);
}
/* update extra sections header */
ans = XR_UpdateExtraSections(
lSeekProc, readProc, writeProc, clientData,
dcdRep.dcd_toPos );
ReturnIfErrorRes(ans);
return 0;
}
/* Add subsec group */
int
XR_AddSubsecGroup(lSeekProc, readProc, writeProc, clientData)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_IOXferProc writeProc;
XR_Pointer clientData;
{
int ans;
int xsecPos;
int xsecBytes;
int xsshPos;
int xsshBytes;
int clientPos;
struct XR_XSubsecHdrRep xsshRep;
/* get extra sections */
ans = XR_GetXSec(lSeekProc, readProc, writeProc, clientData,
&xsecPos, &xsecBytes );
ReturnIfErrorRes(ans);
/* write new end of group subsec */
xsshPos = xsecPos + xsecBytes;
xsshRep.xssh_magic = XR_GetADotOutExtraMagic();
xsshBytes = XR_XSubsecHdr_SetName(&xsshRep,
XR_GetEndOfGroupSubsecName());
ReturnIfErrorRes(xsshBytes);
xsshRep.xssh_subsecBytes = xsshBytes + sizeof(int);
ans = XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData,
xsshPos, &xsshRep);
ReturnIfErrorRes(ans);
clientPos = xsshPos + xsshBytes;
ans = XR_AOXWrite(lSeekProc, writeProc, clientData,
clientPos, &(xsshRep.xssh_subsecBytes), sizeof(int));
ReturnIfWrongRes(ans,sizeof(int),EIO);
/* update and write extra sections hdr */
ans = XR_UpdateExtraSections(
lSeekProc, readProc, writeProc, clientData,
xsshPos + xsshRep.xssh_subsecBytes );
ReturnIfErrorRes(ans);
return clientPos;
}
int
XR_InsertExtraSubsec(lSeekProc, readProc, writeProc, clientData,
subsecName, subsecBytes, subsecPos)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_IOXferProc writeProc;
XR_Pointer clientData;
char * subsecName;
int subsecBytes;
int * subsecPos;
{
int ans;
bool appending;
int xsecPos;
int xsecBytes;
int xsshPos, xsshPosNew;
int xsshBytes, xsshBytesNew;
int suffixBytes;
int groupBytes;
int groupBytesPos;
int clientPos;
struct XR_XSubsecHdrRep xsshRep, xsshRepNew;
appending = ( (subsecPos == NIL) || ((*subsecPos) < 0) );
ans = XR_GetXSec(lSeekProc, readProc, writeProc, clientData,
&xsecPos, &xsecBytes);
ReturnIfErrorRes(ans);
/* find position to insert new subsec */
clientPos = ((appending)
? (xsecPos + xsecBytes - sizeof(int))
: (*subsecPos) );
ans = XR_GetXSubsecHdrFromClientPos(lSeekProc, readProc, clientData,
clientPos, &xsshRep );
ReturnIfErrorRes(ans);
xsshPosNew = xsshPos = (clientPos - ans);
/* construct new header */
xsshRepNew.xssh_magic = XR_GetADotOutExtraMagic();
xsshBytesNew = XR_XSubsecHdr_SetName(&xsshRepNew, subsecName);
ReturnIfErrorRes(xsshBytesNew);
xsshRepNew.xssh_subsecBytes = subsecBytes + xsshBytesNew;
suffixBytes = (xsecPos + xsecBytes) - xsshPosNew;
/* find matching end-of-group section and update its length */
for(;;) {
if( strcmp(xsshRep.xssh_name, XR_GetEndOfGroupSubsecName()) == 0 )
break;
xsshPos += RNDUPWORDSZ(xsshRep.xssh_subsecBytes);
ans = XR_ReadXSubsecHdr(lSeekProc, readProc, clientData,
xsshPos, &xsshRep );
ReturnIfErrorRes(ans);
}
groupBytesPos = xsshPos + xsshRep.xssh_subsecBytes
- (sizeof groupBytes);
ans = XR_AOXRead(lSeekProc, readProc, clientData,
groupBytesPos, &groupBytes, (sizeof groupBytes));
ReturnIfWrongRes(ans, (sizeof groupBytes), EFMT);
groupBytes += RNDUPWORDSZ(xsshRepNew.xssh_subsecBytes);
ans = XR_AOXWrite(lSeekProc, writeProc, clientData,
groupBytesPos, &groupBytes, (sizeof groupBytes));
ReturnIfWrongRes(ans, (sizeof groupBytes), EIO);
/* update and rewrite extra sections header */
ans = XR_UpdateExtraSections(
lSeekProc, readProc, writeProc, clientData,
xsecPos + groupBytes );
ReturnIfErrorRes(ans);
/* shift file suffix right */
ans = ShiftRightInFile(
lSeekProc, readProc, writeProc, clientData,
xsshPosNew,
xsshPosNew+RNDUPWORDSZ(xsshRepNew.xssh_subsecBytes),
suffixBytes );
ReturnIfErrorRes(ans);
/* write new header */
ans = XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData,
xsshPosNew, &xsshRepNew );
ReturnIfErrorRes(ans);
if( subsecPos != NIL ) *subsecPos = xsshPosNew + xsshBytesNew;
return 0;
}
int
XR_StartAddExtraSubsec(lSeekProc, readProc, writeProc, clientData,
subsecName, subsecPos)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_IOXferProc writeProc;
XR_Pointer clientData;
char * subsecName;
int * subsecPos;
{
int ans;
int xsecPos;
int xsecBytes;
int xsshPos;
int xsshBytes;
int clientPos;
int savedGroupBytes;
struct XR_XSubsecHdrRep xsshRep;
if( (subsecName == NIL) || (subsecName[0] == '\0') )
return ResFromErrno(EINVAL);
ans = XR_GetXSec(lSeekProc, readProc, writeProc, clientData,
&xsecPos, &xsecBytes);
ReturnIfErrorRes(ans);
/* position to beginning of new subsec */
clientPos = xsecPos + xsecBytes - (sizeof savedGroupBytes);
ans = XR_AOXRead(lSeekProc, readProc, clientData,
clientPos, &savedGroupBytes, (sizeof savedGroupBytes) );
ReturnIfWrongRes(ans, (sizeof savedGroupBytes), EFMT);
ans = XR_GetXSubsecHdrFromClientPos(
lSeekProc, readProc, clientData,
clientPos, &xsshRep );
ReturnIfErrorRes(ans);
xsshBytes = ans;
if( strcmp(xsshRep.xssh_name, XR_GetEndOfGroupSubsecName()) != 0 )
return ResFromErrno(EFMT);
xsshPos = clientPos - xsshBytes;
/* write new subsec hdr */
xsshRep.xssh_magic = XR_GetADotOutExtraMagic();
xsshBytes = XR_XSubsecHdr_SetName(&xsshRep, subsecName);
ReturnIfErrorRes(xsshBytes);
xsshRep.xssh_subsecBytes = savedGroupBytes; /* until commit */
ans = XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData,
xsshPos, &xsshRep);
ReturnIfErrorRes(ans);
/* update and write extra sections hdr */
ans = XR_UpdateExtraSections(
lSeekProc, readProc, writeProc, clientData,
xsshPos );
ReturnIfErrorRes(ans);
if( subsecPos != NIL ) *subsecPos = xsshPos + xsshBytes;
return 0;
}
int
XR_FinishAddExtraSubsec(lSeekProc, readProc, writeProc, clientData,
subsecBytes)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_IOXferProc writeProc;
XR_Pointer clientData;
int subsecBytes;
{
int ans;
int xsecPos;
int xsecBytes;
int xsshPos;
int xsshBytes;
int clientPos;
int groupBytes;
int roundedSubsecBytes;
struct XR_XSubsecHdrRep xsshRep;
ans = XR_GetXSec(lSeekProc, readProc, writeProc, clientData,
&xsecPos, &xsecBytes);
ReturnIfErrorRes(ans);
/* retrieve groupBytes */
xsshPos = xsecPos + xsecBytes;
xsshBytes = XR_ReadXSubsecHdr( lSeekProc, readProc, clientData,
xsshPos, &xsshRep );
ReturnIfErrorRes(xsshBytes);
groupBytes = xsshRep.xssh_subsecBytes;
/* update and rewrite subsec hdr, update groupbytes */
if( subsecBytes >= 0 ) {
xsshRep.xssh_subsecBytes = xsshBytes + subsecBytes;
roundedSubsecBytes = RNDUPWORDSZ(xsshRep.xssh_subsecBytes);
groupBytes += roundedSubsecBytes;
ans = XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData,
xsshPos, &xsshRep);
ReturnIfErrorRes(ans);
xsshPos += roundedSubsecBytes;
}
/* append end-of-group subsec */
ans = XR_XSubsecHdr_SetName( &xsshRep,
XR_GetEndOfGroupSubsecName() );
ReturnIfErrorRes(ans);
xsshBytes = ans;
xsshRep.xssh_subsecBytes = xsshBytes + (sizeof groupBytes);
roundedSubsecBytes = RNDUPWORDSZ(xsshRep.xssh_subsecBytes);
ans = XR_WriteXSubsecHdr(lSeekProc, writeProc, clientData,
xsshPos, &xsshRep );
ReturnIfWrongRes(ans, xsshBytes, EIO);
ans = XR_AOXWrite(lSeekProc, writeProc, clientData,
xsshPos+xsshBytes, &groupBytes, (sizeof groupBytes) );
ReturnIfWrongRes(ans, (sizeof groupBytes), EIO);
xsshPos += roundedSubsecBytes;
/* update and write extra sections hdr */
ans = XR_UpdateExtraSections(
lSeekProc, readProc, writeProc, clientData,
xsshPos );
ReturnIfErrorRes(ans);
return 0;
}
int
XR_DeleteAllExtraSubsecs(lSeekProc, readProc, writeProc, fTruncateProc,
clientData)
XR_IOPositionProc lSeekProc;
XR_IOXferProc readProc;
XR_IOXferProc writeProc;
XR_IOPositionProc fTruncateProc;
XR_Pointer clientData;
{
int ans;
int xsecPos;
int xsecBytes;
ans = XR_GetXSec(lSeekProc, readProc, NIL, clientData,
&xsecPos, &xsecBytes);
ReturnIfErrorRes(ans);
ans = XR_UpdateExtraSections(
lSeekProc, readProc, writeProc, clientData,
xsecPos );
ReturnIfErrorRes(ans);
ans = (*fTruncateProc)(xsecPos, L_SET, clientData);
ReturnIfErrorRes(ans);
return 0;
}